//
//  ArrayExample.swift
//  SwiftTest
//
//  Created by bym on 2019/8/7.
//  Copyright © 2019 ZZ. All rights reserved.
//

import UIKit

class ArrayExample: NSObject {
	override init() {
		super.init()
		self.reduce()
	}
}

//sorted
extension ArrayExample{
	/// 排序
	/// 闭包做参数
	func sort() {
		/*
		sort1
		数组提供了一个排序函数，sorted().使用的是默认规则，当然我们也可以定制排序规则。
		*/
		
		let names = ["ZZZZZZ", "BB", "A", "CCCC", "EEEEE"]
		let sortedNames0 = names.sorted()
		ZZLog(sortedNames0);
		// ["A", "BB", "CCCC", "EEEEE", "ZZZZZZ"]
		
		/**
		sort2 (函数重载)
		@inlinable public func sorted(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> [Element]
		
		@inlinable : 开发者可以将一些公共功能注释为@inlinable。这给编译器提供了优化跨模块边界的泛型代码的选项
		
		外部参数名by  内部参数areInIncreasingOrder
		
		throws/rethrows
		throws用在可能出现异常的函数或者方法中，而rethrows针对的不是函数或者方法的本身，
		而是它携带的闭包类型的参数，当它的闭包类型的参数throws的时候，我们要使用rethrows
		继续将这个异常往上传递， 直到被调用者使用到。
		*/
		do {
			let sortedNames1 = names.sorted {
				$0.count > $1.count
			}
			ZZLog(sortedNames1)
			// ["ZZZZZZ", "EEEEE", "CCCC", "BB", "A"]
		} catch let err as Error {
			ZZLog(err)
		}
	}
}

//forEach
extension ArrayExample{
	func forEach() {
		/*
		循环遍历集合中的元素，相当于for-in 快速遍历
		*/
		let values = [5, 3, 2, 3,1]
		values.forEach {
			ZZLog("element is \($0)")
		}
	}
}

//filter
extension ArrayExample{
	func filter() {
		/*
		函数原型:
		func filter(_ isIncluded: (Element) -> Bool) -> [Element]
		
		按照规则过滤原数组
		*/
		
		let values = [1.5, 10, 4.88, 3.2, 8]
		let res = values.filter {
			return $0 > 4
		}
		ZZLog(res)
	}
}

//map flatMap compactMap
extension ArrayExample{
	func map() {
		/*
		函数原型：
		students.map(<#T##transform: (String) throws -> T##(String) throws -> T#>)
		
		数组映射
		*/
		let input = ["0", "12", "name", "hi", "3"]
		
		let number = input.map {
			Int($0) //将元素转换为Int型
		}
		
		ZZLog(number)
		//注意类型转换可能失败，所以返回的是可选型
		//[Optional(0), Optional(12), nil, nil, Optional(3)]
		
		/*
		另外一个高度近似的函数
		flatMap
		隐含了两种操作
		1.解包
		2.展开并合并
		*/
		//'flatMap' is deprecated: Please use compactMap(_:) for the case where closure returns an optional value Use 'compactMap(_:)' instead
		let flatNumber = input.flatMap() {
			Int($0)
		}
		ZZLog(flatNumber)
		//[0, 12, 3]
		
		let compactNumber = input.compactMap {
			Int($0)
		}
		ZZLog(compactNumber)
	}
}

//reduce
extension ArrayExample{
	
	func reduce(){
		/*
		函数原型
		reduce(<#T##initialResult: Result##Result#>, <#T##nextPartialResult: (Result, String) throws -> Result##(Result, String) throws -> Result#>)
		*/
		
		//数组
		let flatNumber = [0, 12, 3]
		let sum = flatNumber.reduce(0) {
			return $0 + $1
		}
		//15
		ZZLog(sum)
		//字典
		let stock : [Double : Double] = [1.5: 5.0, 10: 2.0, 4.99: 20.0, 2.30: 5.0, 8.19: 30.0]

		let stockSum = stock.reduce(0) {
			return $0 + $1.key * Double($1.value)
		}
		ZZLog(stockSum)
		//384.5
		
		let festivals = ["NewYear",
						 "SpringFestival",
						 "LabourDay",
						 "Mid-AutumnFestival",
						 "NationalDay"]
		// 将数组中的每个字符串用”、“拼接
		let str = festivals.reduce("$") { (str1, str2) -> String in
			ZZLog(str1)
			ZZLog(str2)
			ZZLog("---------")
			return str1 == "$" ? str2 : str1 + "、" + str2
		}
		
		ZZLog(str)
		
		/*
		另一个reduce重载函数
		注意inout 关键字，所以想想你可以怎么应用？
		*/
//		input.reduce(into: <#T##Result#>) { (<#inout Result#>, <#String#>) in
//			<#code#>
//		}
	}
}
